package org.jzs.mybaseapp.common.retorift;

import android.content.Context;
import android.text.TextUtils;
import android.widget.Toast;

import com.google.gson.Gson;

import org.jzs.mybaseapp.Applications;
import org.jzs.mybaseapp.MyApplaciton;
import org.jzs.mybaseapp.common.base.BaseEntity;
import org.jzs.mybaseapp.common.system.AppConfig;
import org.jzs.mybaseapp.common.utils.AppLog;
import org.jzs.mybaseapp.section.home.entity.CourseEntity;

import java.util.Map;
import java.util.concurrent.TimeUnit;

import me.jessyan.progressmanager.ProgressManager;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * Created by Jzs on 2017/7/28.
 */

public class RetrofitManager {
    private static RetrofitManager mRetrofitManager;
    private Retrofit mRetrofit;
    private ApiService apiService;
    public static String baseUrl = AppConfig.BASE_URL;


    private RetrofitManager() {
        initRetrofit();
    }

    private RetrofitManager(String url) {
        initRetrofit(url);
    }

    public static synchronized RetrofitManager getInstance() {
        return new RetrofitManager();
    }

    public static synchronized RetrofitManager getInstance(String url) {
        return new RetrofitManager(url);
    }

    private void initRetrofit() {
        initRetrofit("");
    }

    private void initRetrofit(String url) {
        if (TextUtils.isEmpty(url)) {
            url = baseUrl;
        }
        HttpLoggingInterceptor LoginInterceptor = new HttpLoggingInterceptor(
                message -> {
                    //打印retrofit日志
                    AppLog.e("Okhttp", message);
                }
        );
        LoginInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);


        //创建okhttpclient
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (url.equals(AppConfig.BASE_URL)) {
            //添加检查拦截器，可在拦截器中设置全局的header和根据不同的返回值操作
            builder.addInterceptor(new RspCheckInterceptor());
        }

        builder.addInterceptor(LoginInterceptor); //添加retrofit日志打印
        builder.connectTimeout(15, TimeUnit.SECONDS);
        builder.readTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS);
        builder.retryOnConnectionFailure(true);
        OkHttpClient client =  ProgressManager.getInstance().with(builder).build();//添加下载进度监听

        mRetrofit = new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .client(client)
                .build();
    }

    public <T> T createReq(Class<T> reqServer) {
        return mRetrofit.create(reqServer);
    }

    public RetrofitManager createBaseApi() {
        apiService = createReq(ApiService.class);
        return this;
    }

    /**
     * 一般的post的请求，直接将对象返回
     *
     * @param url
     * @param parame
     * @param mCallback
     * @param aClass
     */
    public void post( String url, Map<String, String> parame,
                     final RequestCallBack mCallback, final Class<?> aClass) {
        apiService.executePost(url, parame)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new BaseSubscriber<ResponseBody>() {
                    @Override
                    public void onNext(ResponseBody entity) {
                        Gson gson = new Gson();
                        String response = null;
                        try {
                            response = entity.string();
                            AppLog.e(response);
                            Object object = gson.fromJson(response, aClass);
                            mCallback.onSuccess(200, "请求成功", object);
                        } catch (Exception e) {
                            e.printStackTrace();
                            AppLog.e("解析失败，entity：" + response);
                            mCallback.onFailure(500, "请求失败", entity);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        super.onError(e);

                    }
                });
    }

    /**
     * 一般的get请求
     *
     * @param url
     * @param parame
     * @param mCallback
     * @param aClass
     */
    public void get( String url, Map<String, String> parame,
                    final RequestCallBack mCallback, final Class<?> aClass) {
        apiService.executeGet(url, parame)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new BaseSubscriber<Object>() {
                    @Override
                    public void onNext(Object entity) {
                        Gson gson = new Gson();
                        String response = null;
                        try {
                            response = entity.toString();
                            AppLog.e(response);
                            Object object = gson.fromJson(response, aClass);
                            mCallback.onSuccess(200, "请求成功", object);
                        } catch (Exception e) {
                            e.printStackTrace();
                            AppLog.e("解析失败，entity：" + response);
                            mCallback.onFailure(500, "请求失败", entity);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        super.onError(e);
                    }
                });
    }

    /**
     * post json请求
     * @param url
     * @param parame
     * @param jsonParame
     * @param mCallback
     * @param aClass
     */
    public void postJson( String url, Map<String, String> parame, Map<String, String> jsonParame,
                         final RequestCallBack mCallback, final Class<?> aClass) {
        RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), new Gson().toJson(jsonParame));

        apiService.json(url, parame, body)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new BaseSubscriber<Object>() {
                    @Override
                    public void onNext(Object entity) {
                        ResponseBody entity1 = (ResponseBody) entity;
                        Gson gson = new Gson();
                        String response = null;
                        try {
                            response = entity1.string();
                            AppLog.e(response);
                            Object object = gson.fromJson(response, aClass);
                            mCallback.onSuccess(200, "请求成功", object);
                        } catch (Exception e) {
                            e.printStackTrace();
                            AppLog.e("解析失败，entity：" + response);
                            mCallback.onFailure(500, "请求失败", entity);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        super.onError(e);
                    }
                });
    }

    /**
     * 根据项目的一个封装，RESTful规范
     * 通过 BaseEntity 的 code 来进行状态判断和 aClass 来进行 Gson 转换，直接返回实体类
     *
     * @param url
     * @param parameters
     * @param mCallback
     * @param aClass
     */
    public void packagePost( String url, Map<String, String> parameters, final RequestCallBack mCallback, final Class<?> aClass) {
        apiService.executePost(url, parameters)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new BaseSubscriber<ResponseBody>() {
                    @Override
                    public void onNext(ResponseBody entity) {
                        Gson gson = new Gson();
                        String response = null;
                        try {
                            response = entity.string();
                            AppLog.e(response);
                            BaseEntity object = (BaseEntity) gson.fromJson(response, aClass);
                            if (object.code == 1 || object.code == 2) {
                                mCallback.onSuccess(object.code, object.msg, object);
                            } else if (object.code == 9) {
                                Toast.makeText(Applications.context(), "您的账号已在其他地方登录", Toast.LENGTH_SHORT).show();
                            } else {
                                mCallback.onFailure(object.code, object.msg, object);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            AppLog.e("解析失败，entity：" + response);
                            mCallback.onFailure(500, "解析失败", entity);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        super.onError(e);
                        mCallback.onFailure(500, "解析失败", null);
                    }
                });
    }


    public void download(String url, final DownloadCallBack callBack) {
        apiService.downloadFile(url)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new DownSubscriber<ResponseBody>(callBack));
    }
}